﻿using FyCaches.Core.Exceptions;
using FyCaches.Models;
using FySystem.Converter;
using FySystem.Extension;
using FySystem.IOTFlow;
using FySystem.Net.SimSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FyCaches.Core.Services
{
    class CommandService
    {
        /// <summary>
        /// 处理客户端的消息
        /// data结构如下：
        /// 0-15：用户和密码经过MD5加密后的结果
        /// 16-19：版本号，预留
        /// 20-35：请求id
        /// 36-37：缓存库索引
        /// 38-39：指令（数字）
        /// 40-N：指令参数
        /// ---------------------------------------
        /// 返回结果的data格式如下：
        /// 0-15：请求id
        /// 16：0表示正常，1表示执行失败
        /// 如果执行失败：
        ///     17-20：错误代码
        ///     21-N：错误消息
        /// 如果执行成功：
        ///     17-18：指令
        ///     19-N：执行结果数据
        /// </summary>
        /// <param name="simClient"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        internal static void HandleMsgs(SimClient simClient, FrameInfo frame)
        {
            byte[] requestId = null;
            CommandInfo commandInfo = new CommandInfo();
            try
            {
                string authMd5 = NumberConversion.BytesToHexString(frame.Frame, 0, 16, false);

                commandInfo.Version = BitConverter.ToUInt32(frame.Frame, 16);
                commandInfo.RequestId = frame.Frame.AsSpan(20, 16).ToArray();
                commandInfo.DbIndex = BitConverter.ToUInt16(frame.Frame, 36);
                commandInfo.Command = frame.Frame.AsSpan(38, 2).ToArray();
                commandInfo.Frame = frame;
                commandInfo.SimClient = simClient;

                //校验权限
                bool hasRights = AuthService.AuthUser(authMd5);
                if (hasRights == false)
                    throw CExceptions.CreateException(Exceptions.Exceptions.账号校验失败);

                CacheFlowService.CacheFlows[commandInfo.DbIndex].Enqueue(commandInfo);
            }
            catch (Exception ex)
            {
                List<byte> response = PackUtils.CreatePackByException(requestId, ex);
                SendToClient(simClient, response);
            }
        }

        /// <summary>
        /// 将数据返回给客户端
        /// </summary>
        /// <param name="simClient"></param>
        /// <param name="data"></param>
        internal static void SendToClient(SimClient simClient,List<byte> data)
        {
            try
            {
                if (data != null && simClient != null)
                    simClient.Send(data);
            }
            catch (Exception ex)
            {
                FyLogContext.Write($"发送数据失败,response:{ex.Message}");
            }
        }
    }
}
